package tech.summerly.weather.component.activities

import android.arch.lifecycle.ViewModelProviders
import android.content.Intent
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.os.Bundle
import android.support.design.widget.Snackbar
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.GridLayoutManager
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.helper.ItemTouchHelper
import android.view.View
import androidx.core.graphics.withTranslation
import kotlinx.android.synthetic.main.activity_city_manager.*
import org.jetbrains.anko.dip
import tech.summerly.weather.R
import tech.summerly.weather.component.adapter.UserRegionAdapter
import tech.summerly.weather.component.fragments.RegionSelectorFragment
import tech.summerly.weather.component.viewmodel.UserRegionViewModel
import tech.summerly.weather.model.Region
import tech.summerly.weather.model.UserRegion
import tech.summerly.weather.util.*
import kotlin.math.abs

class UserRegionManagerActivity : AppCompatActivity(), RegionSelectorFragment.Container {

    companion object {
        const val TAG_FRAGMENT_CITY_FILTER = "city_filter"

        const val ACTION_ADD_CITY = "to_city_filter"
    }

    private val cityListViewModel by lazy {
        ViewModelProviders.of(this, UserRegionViewModel).get(UserRegionViewModel::class.java)
    }

    private val userRegionAdapter by lazy { UserRegionAdapter(itemClickCallback) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_city_manager)
        initView()
        loadData()
        subscribeUI()
    }

    private fun subscribeUI() {
        cityListViewModel.regionList.observe(this) { list: List<UserRegion>? ->
            log { list }
            if (list == null || list.isEmpty()) {
                setEmptyListDesc(true)
            } else {
                setEmptyListDesc(false)
                showCityList(list)
            }
        }
    }

    private fun showCityList(regionList: List<UserRegion>) {
        userRegionAdapter.submitList(regionList)
    }


    private fun initView() {
        toolbar.setNavigationOnClickListener {
            finish()
        }
        fabAdd.setOnClickListener {
            supportFragmentManager.inTransaction {
                val fragment = RegionSelectorFragment()
                replace(android.R.id.content, fragment, TAG_FRAGMENT_CITY_FILTER)
                addToBackStack(TAG_FRAGMENT_CITY_FILTER)
            }
        }
        cityList.adapter = userRegionAdapter
        cityList.setSwipeAble(
                onItemSwiped = {
                    val remove = userRegionAdapter.removeAt(it)
                    cityListViewModel.remove(remove)
                    remove
                },
                onItemRevoked = { position: Int, value: Any ->
                    if (value is UserRegion) {
                        userRegionAdapter.add(position, value)
                        cityListViewModel.add(value)
                    }
                },
                onItemMoved = { from, to ->
                    val o1 = userRegionAdapter.removeAt(from)
                    val previous = userRegionAdapter.getItemOrNull(to - 1)
                    val next = userRegionAdapter.getItemOrNull(to)
                    userRegionAdapter.add(to, o1)
                    cityListViewModel.move(o1, previous, next)
                    true
                },
                isItemInteractive = { _, _ ->
                    true
                })
    }

    private fun setEmptyListDesc(show: Boolean) {
        if (!show) {
            textEmptyDesc.visibility = View.GONE
        } else {
            textEmptyDesc.visibility = View.VISIBLE
        }
    }


    private val itemClickCallback = fun(userRegion: UserRegion) {
        finish()
        val intent = Intent(this, MainActivity::class.java)
        intent.putExtra(MainActivity.KEY_REGION, userRegion.region)
        startActivity(intent)
    }

    private fun loadData() {
        if (intent.getBooleanExtra(ACTION_ADD_CITY, false)) {
            fabAdd.performClick()
        }
    }

    private fun addRegion(region: Region) {
        for (i in 0..userRegionAdapter.itemCount - 1) {
            if (userRegionAdapter.getItem(i).fullAddress == region.fullName) {
                toast(getString(R.string.template_location_exgists, region.name))
                return
            }
        }
        cityListViewModel.add(UserRegion.new(region))
    }

    override fun onRegionSelected(region: Region) {
        addRegion(region)
        val fragment = supportFragmentManager.findFragmentByTag(TAG_FRAGMENT_CITY_FILTER)
        fragment?.let {
            supportFragmentManager.inTransaction {
                remove(it)
            }
        }
    }

    /**
     * 让 RecyclerView 可以左滑删除
     * @param onItemSwiped 响应左滑删除时的调用
     * @param onItemRevoked 响应撤回删除时的调用
     */
    private fun <T : Any> RecyclerView.setSwipeAble(
            onItemSwiped: (position: Int) -> T,
            onItemRevoked: (position: Int, value: T) -> Unit,
            onItemMoved: (from: Int, to: Int) -> Boolean,
            isItemInteractive: (position: Int, actionState: Int) -> Boolean
    ) = ItemTouchHelper(object : ItemTouchHelper.Callback() {
        override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
            val dragFlag = ItemTouchHelper.UP or ItemTouchHelper.DOWN
            val swipeFlag = ItemTouchHelper.START or ItemTouchHelper.END
            return when (layoutManager) {
                is GridLayoutManager -> makeMovementFlags(dragFlag or swipeFlag, 0)
                is LinearLayoutManager -> makeMovementFlags(dragFlag, swipeFlag)
                else -> makeMovementFlags(0, 0)
            }
        }

        //用 int 和 T 键值对临时保存所擦除的那一项的 位置 和  数据
        var removed: Pair<Int, T?> = -1 to null

        override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
            val from = viewHolder.adapterPosition
            val to = target.adapterPosition
            val b = onItemMoved(from, to)
            if (b) {
                adapter.notifyItemMoved(from, to)
            }
            return b
        }

        override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
            val adapterPosition = viewHolder.adapterPosition
            removed = adapterPosition to onItemSwiped(adapterPosition)
            adapter.notifyItemRemoved(adapterPosition)
            Snackbar.make(this@setSwipeAble, context.getString(R.string.undo_description), Snackbar.LENGTH_LONG)
                    .setAction(context.getString(R.string.undo), {
                        val position = removed.first
                        val value = removed.second
                        if (position == -1 || value == null) {
                            return@setAction
                        }
                        onItemRevoked(position, value)
                        adapter.notifyItemInserted(position)
                    })
                    .show()
        }

        private val iconDelete by lazy {
            getDrawable(R.drawable.ic_delete_black_24dp)
                    .also {
                        it.setTint(color(R.color.color_text_primary_inverse))
                        val dip = dip(24)
                        it.setBounds(0, 0, dip, dip)
                    }
        }

        private val rectSwipBackground = Rect()

        private val paint = Paint()

        override fun onChildDraw(c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
            val position = viewHolder.adapterPosition
            if (position != -1 && isItemInteractive(position, actionState)) {
                if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {

                    val backgroundWith: Int = abs(dX).toInt()
                    val left: Int = if (dX < 0) {
                        viewHolder.itemView.width + dX.toInt()
                    } else {
                        0
                    }
                    rectSwipBackground.set(left, viewHolder.itemView.top, left + backgroundWith, viewHolder.itemView.bottom)
                    paint.color = Color.RED
                    c.drawRect(rectSwipBackground, paint)
                    c.withTranslation((left + dip(16).toFloat()),
                            (viewHolder.itemView.top + (viewHolder.itemView.height - iconDelete.bounds.height()) / 2).toFloat()
                    ) {
                        iconDelete.draw(this)
                    }
                }
                super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
            }
        }

    }).attachToRecyclerView(this@setSwipeAble)

}
